package com.ray.util;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.joda.time.DateTime;

import com.google.appengine.repackaged.com.google.common.collect.ImmutableMap;
import com.ray.bean.AttendOvertimeRuleBean;
import com.ray.pojo.attend.AttendanceDailyInfoPojo;
import com.ray.pojo.attend.WorkdateClockInfo;

import net.sf.json.JSONObject;

/**
 * 考勤相关工具类
 * @author 王荣
 *
 */
public class AttendanceUtil {
	
	/**
	 * 锁对象
	 */
	//private static final Object lockObj = new Object();
	//每一个线程
	//private static Map<String, ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
	
	public final static String TIME_RESULT_LEAVE = "leave";
	public final static String TIME_RESULT_NORMAL = "normal";
	public final static String TIME_RESULT_LACK = "lack";
	public final static String TIME_RESULT_LATE = "late";
	public final static String TIME_RESULT_EARLY = "early";
	public final static String TIME_RESULT_REST = "rest";
	
	/** yyyy-MM-dd HH:mm:ss */
	/*public  static SimpleDateFormat SDF = getSdf("yyyy-MM-dd HH:mm:ss");
	*//** yyyy-MM-dd HH:mm *//*
	public  static SimpleDateFormat SDF_NOSECOND = getSdf("yyyy-MM-dd HH:mm");
	*//** yyyy-MM-dd *//*
	public  static SimpleDateFormat SDF_DATE =getSdf("yyyy-MM-dd");*/
	
	
	/**
       * 返回一个ThreadLocal的sdf,每个线程只会new一次sdf
     * 
     * @param pattern
     * @return
     */
    /*private static SimpleDateFormat getSdf(final String pattern) {
        ThreadLocal<SimpleDateFormat> tl = sdfMap.get(pattern);
        // 此处的双重判断和同步是为了防止sdfMap这个单例被多次put重复的sdf
        if (tl == null) {
            synchronized (lockObj) {
                tl = sdfMap.get(pattern);
                if (tl == null) {
                    // 只有Map中还没有这个pattern的sdf才会生成新的sdf并放入map
                    //System.out.println("put new sdf of pattern " + pattern + " to map");
                    // 这里是关键,使用ThreadLocal<SimpleDateFormat>替代原来直接new SimpleDateFormat
                    tl = new ThreadLocal<SimpleDateFormat>() {
                        @Override
                        protected SimpleDateFormat initialValue() {
                            //System.out.println("thread: " + Thread.currentThread() + " init pattern: " + pattern);
                            return new SimpleDateFormat(pattern);
                        }
                    };
                    sdfMap.put(pattern, tl);
                }
            }
        }
        return tl.get();
    }*/
	/**
	 * 判断这个人当月的请假、补卡、迟到早退次数或时长是否为当月最多或最长
	 * @param duration 这个人的当月次数或时长
	 * @param durationMaximum 当月最大次数或时长
	 * @param maximumPerson 当前最大人的信息list
	 * @param userName 这个人的姓名
	 * @return List 最多或最长的人的信息 userName,maximum
	 * @author 王荣
	 */
	public static List<Map<String, Object>> judgeMaximum(long t, long maximum, List<Map<String, Object>> maximumPerson, String userName) {
		Map<String, Object> maximumMap = new HashMap<>();
		if(t>maximum) maximumPerson.clear();
		maximumMap.put("userName", userName);
		maximumMap.put("maximum", t);
		maximumPerson.add(maximumMap);
		return maximumPerson;
	}

	/**
	 * 有效工时与旷工时长，有效工作时长的计算还差一点：休息开始-休息结束，应减去休息时长
	 * @param leaveList 请假信息
	 * @param ondutyBase 上班时间
	 * @param ondutyCheck 上班打卡时间
	 * @param ondutyResult 上班打卡结果
	 * @param offdutyBase 下班时间
	 * @param offdutyCheck 下班打卡时间
	 * @param offdutyResult 下班打卡结果
	 * @return
	 * @throws ParseException
	 * @author 王荣
	 */
	public static Map<String, Object> getEffectiveTimeInfo(List<Map<String, Object>> leaveList,
			String ondutyBase,String ondutyCheck,String ondutyResult,
			String offdutyBase,String offdutyCheck,String offdutyResult) throws ParseException {
		
		//正常或缺卡时 用基础上下班时间计算
		long ondutyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(ondutyBase).getTime(),offdutyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(offdutyBase).getTime();
		//迟到或早退时 用实际上下班时间计算
		if(AttendanceUtil.TIME_RESULT_LATE.equals(ondutyResult)) ondutyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(ondutyCheck).getTime();
		if(AttendanceUtil.TIME_RESULT_EARLY.equals(offdutyResult)) offdutyTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(offdutyCheck).getTime();
		Map<String, Object> effectiveInfoMap = new HashMap<>();
		//有效工作时长，请假时长，旷工时长
		long effectiveDuration = offdutyTime-ondutyTime,leaveDuration = 0,absentDuration = 0;
		if(leaveList!=null && leaveList.size()>0) {
			int leaveSize = leaveList.size();
			for(int leaveIdx=0;leaveIdx<leaveSize;leaveIdx++) {
				Map<String, Object> leaveMap = leaveList.get(leaveIdx);
				//此次请假信息
				long startTime = Long.valueOf(leaveMap.get("startTime").toString()),
					endTime = Long.valueOf(leaveMap.get("endTime").toString());
				//如果请假时间范围完全包括打卡时间 请假开始<上班<下班<请假结束
				if(startTime<=ondutyTime && offdutyTime<=endTime) {
					leaveDuration += effectiveDuration;
					break;
				}
				//如果请假完全在打卡时间范围外  请假开始<请假结束<上班<下班 || 上班<下班<请假开始<请假结束
				if(endTime<=ondutyTime || offdutyTime<=startTime) {
					continue;
				}
				//请假范围完全在打卡范围内 上班<请假开始<请假结束<下班
				if(ondutyTime<=startTime && endTime<=offdutyTime) {
					leaveDuration += endTime-startTime;
				}else if(startTime<=ondutyTime) {
					//请假开始在上班时间之前  请假开始<上班<请假结束<下班
					leaveDuration += endTime-ondutyTime;
				}else if(offdutyTime<=endTime) {
					//请假结束在下班时间之后 上班<请假开始<下班<请假结束
					leaveDuration += offdutyTime-startTime;
				}
			}
		}
		//有缺卡
		if(ondutyCheck==null || offdutyCheck==null) {
			//如果不是(上下班只有一次缺卡，并且缺卡在请假范围内)，计入旷工
			if(	!((
					(ondutyCheck==null && offdutyCheck!=null)//上班缺卡，下班不缺卡
					|| (ondutyCheck!=null && offdutyCheck==null)//上班不缺卡，下班缺卡
				) 
				&& leaveDuration>0 
				&& isLeave(leaveList, ondutyCheck == null ? ondutyTime : offdutyTime)
				)) {
				absentDuration = offdutyTime-ondutyTime-leaveDuration;
				effectiveInfoMap.put("absentDuration", absentDuration);
			}
		}
		
		effectiveDuration -= leaveDuration+absentDuration;
		effectiveDuration = effectiveDuration < 0 ? 0 : effectiveDuration;
		effectiveInfoMap.put("ondutyBase", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ondutyBase).getTime());
		effectiveInfoMap.put("ondutyCheck", ondutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(ondutyCheck).getTime());
		effectiveInfoMap.put("offdutyBase", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(offdutyBase).getTime());
		effectiveInfoMap.put("offdutyCheck", offdutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(offdutyCheck).getTime());
		effectiveInfoMap.put("duration", effectiveDuration);
		return effectiveInfoMap;
	}
	
	/**
	 * 计算加班时长
	 * @param offdutyBase 下班基准时间
	 * @param offdutyCheck 下班打卡时间
	 * @param overtimeRuleBean 加班规则
	 * @param overtimeInfoList 加班审批信息
	 * @param isRest 是否休息
	 * @return
	 * @author 王荣
	 * @throws ParseException 
	 */
	public static Map<String, Object> getOvertimeInfo(String offdutyBase,String offdutyCheck,
			AttendOvertimeRuleBean overtimeRuleBean,
			List<Map<String, Object>> overtimeInfoList) throws ParseException{
		if(overtimeRuleBean==null) overtimeRuleBean = new AttendOvertimeRuleBean();
		Integer calcType = overtimeRuleBean.getCalcType(),//计算方式 1：需要审批，2：不需要审批，3：不允许加班 
				durationType = overtimeRuleBean.getDurationType();//加班时间计算 1：以审批单为准，2：以打卡时间为准
		long baseTime = 0,checkTime = 0,
				overtimeDuration = 0,approvalDuration = 0;
		offdutyCheck = offdutyCheck == null ? offdutyBase : offdutyCheck;
		baseTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(offdutyBase).getTime();
		checkTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(offdutyCheck).getTime();
		//允许加班
		if(calcType!=3) {
			long timeUnit = overtimeRuleBean.getTimeUnit()*60*1000;//最小加班时间
			//以打卡为准 计算打卡加班时长
			if(durationType==2) {
				overtimeDuration = checkTime-baseTime;
				if(overtimeDuration<timeUnit) overtimeDuration = 0;
			}
			if(calcType==1) {//需要审批
				if(overtimeInfoList!=null && overtimeInfoList.size()>0) {
					//遍历审批单，计算当天内的审批加班时长
					for(Map<String, Object> overtimeInfo : overtimeInfoList) {
						long overtimeStart = Long.valueOf(overtimeInfo.get("startTime").toString());
						long overtimeEnd = Long.valueOf(overtimeInfo.get("endTime").toString());
						approvalDuration += overtimeEnd-overtimeStart;
					}
					if(approvalDuration<timeUnit) approvalDuration = 0;
				}
				if(overtimeInfoList!=null && overtimeInfoList.size()>0) {
					//以打卡为准，但不能超出审批单时长
					if(durationType==2 && overtimeDuration>approvalDuration) {
						overtimeDuration = approvalDuration;
					}else if(durationType==1) {
						//以审批单为准
						overtimeDuration = approvalDuration;
					}
				}
			}
		}
		if(overtimeDuration==0) return null;
		return new ImmutableMap.Builder<String,Object>()
				.put("baseTime", baseTime)
				.put("checkTime", checkTime)
				.put("duration", overtimeDuration)
				.build();
	}
	
	/**
	 * 计算一天的工作时长
	 * @param clockList 打卡记录
	 * @param leaveApprovalList 请假审批
	 * @param overtimeApprovalList 加班审批
	 * @param attendOvertimeRuleBean 加班规则
	 * @param className 班次名称
	 * @param attendanceTime 打卡时间
	 * @return 一天的工作时长
	 * @author 王荣
	 * @throws ParseException 
	 */
	public static Long getWorkdateDuration(List<Map<String, Object>> clockList,
										   List<Map<String, Object>> leaveApprovalList,
										   List<Map<String, Object>> overtimeApprovalList,
										   AttendOvertimeRuleBean attendOvertimeRuleBean,
										   String className, String attendanceTime) throws ParseException {
		//重新排序
		clockList.sort((Map<String,Object> h1,Map<String,Object> h2) -> ( h1.get("baseCheckTime")+"").compareTo(h2.get("baseCheckTime")+""));
		long duration = 0;
		int clockTimes = attendanceTime==null?0:attendanceTime.replace(" ", "-").split("-").length;
		for(int clockIdx=0;clockIdx<clockList.size();clockIdx++) {
			if(clockIdx%2==1) {
				Map<String, Object> ondutyClockInfo = clockList.get(clockIdx-1);
				Map<String, Object> offdutyClockInfo = clockList.get(clockIdx);
				String ondutyResult = ondutyClockInfo.get("timeResult").toString(),//上班打卡结果
					offdutyResult = offdutyClockInfo.get("timeResult").toString();//下班打卡结果
				Long ondutyBase = Long.valueOf(ondutyClockInfo.get("baseCheckTime").toString()),//上班时间
						ondutyCheck = ondutyClockInfo.get("userCheckTime") == null ? null : Long.valueOf(ondutyClockInfo.get("userCheckTime").toString()),//上班打卡时间
						offdutyBase = Long.valueOf(offdutyClockInfo.get("baseCheckTime").toString()),//下班时间
						offdutyCheck = offdutyClockInfo.get("userCheckTime") == null ? null : Long.valueOf(offdutyClockInfo.get("userCheckTime").toString());//下班打卡时间
				//有效工作时长、旷工时长
				if(className!=null) {
					Map<String, Object> effectiveMap = AttendanceUtil.getEffectiveTimeInfo(leaveApprovalList,
							new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(ondutyBase)), ondutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(ondutyCheck)), ondutyResult,
									new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(offdutyBase)), offdutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(offdutyCheck)), offdutyResult);
					duration += Long.valueOf(effectiveMap.get("duration").toString());
				}
				//加班时长
				if(className==null || (clockIdx>clockTimes-1 && clockList.size()>clockTimes)) {
					//休息加班 || 多打两次卡的加班
					Map<String, Object> overtimeMap = AttendanceUtil.getOvertimeInfo(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(ondutyCheck)), 
							offdutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(offdutyCheck)), attendOvertimeRuleBean,overtimeApprovalList);
					if(overtimeMap!=null) duration += Long.valueOf(overtimeMap.get("duration").toString());
				}else if(clockIdx==clockTimes-1 && clockList.size()==clockTimes) {
					//连班计算加班
					Map<String, Object> overtimeMap = AttendanceUtil.getOvertimeInfo(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(offdutyBase)), 
							offdutyCheck == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(offdutyCheck)), attendOvertimeRuleBean,overtimeApprovalList);
					if(overtimeMap!=null) duration += Long.valueOf(overtimeMap.get("duration").toString());
				}
			}
		}
		return duration;
	}
	
	/**
	 * 将list中对象的时间字符串转换为时间戳
	 * @param convertList 要转换的list
	 * @param propertys 要转换的属性数组
	 * @return
	 * @author 王荣
	 */
	public static List<Map<String, Object>> convertProperty2Timestamp(List<Map<String, Object>> convertList,String[] propertys) {
		for(Map<String, Object> convertMap : convertList) {
			for(String property : propertys) {
				Object time = convertMap.get(property);
				try {
					convertMap.put(property, time == null ? null :new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(time.toString()).getTime());
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
		}
		return convertList;
	}
	
	/**
	 * 获取每日统计后的有效工作小时、迟到早退扣款、请假小时数、加班小时数
	 * @param attendanceDailyInfoPojo 每日统计信息
	 * @param punishList 迟到早退扣款设定
	 * @return 有效工作小时、迟到早退扣款、请假小时数、加班小时数
	 * @author 王荣
	 */
	public static Map<String, Double> getAttendanceDailyInfo(AttendanceDailyInfoPojo attendanceDailyInfoPojo,List<Map<String, Double>> punishList,double hourlySalary){
		List<Map<String, Object>> effectiveTimeInfoList = attendanceDailyInfoPojo.getEffectiveTimeInfoList();
		double effectiveTimeHours = 0;//有效工作小时数
		double absentTimeHours = 0;
		for(Map<String, Object> effectiveTimeMap : effectiveTimeInfoList) {
			effectiveTimeHours += Double.valueOf(effectiveTimeMap.get("duration").toString())/1000/60/60;
			Object absentDuration = effectiveTimeMap.get("absentDuration");
			absentDuration = absentDuration==null ? 0 : absentDuration;
			absentTimeHours += Double.valueOf(absentDuration.toString())/1000/60/60;
		}
		List<Map<String, Object>> lateInfoList = attendanceDailyInfoPojo.getLateInfoList();
		double lateDeduction = 0;//迟到扣款
		for(Map<String, Object> lateInfoMap : lateInfoList) {
			double lateDuration = Double.valueOf(lateInfoMap.get("duration").toString())/1000/60;
			if(lateDuration>0) {
				for(Map<String, Double> punishMap : punishList) {
					if(punishMap==null || punishMap.get("clocking")==null || punishMap.get("clocking")<=0) {
						break;
					}
					if(lateDuration<=punishMap.get("clocking")) {
						lateDeduction += punishMap.get("clockingCharge");
						break;
					}
				}
				//如果迟到分钟数大于设定的值，根据时薪扣款，即：迟到40分钟，扣正常工作40分钟的工资
				if(lateDeduction==0) lateDeduction += lateDuration*(hourlySalary/60);
			}
		}
		double earlyDeduction = 0;//早退扣款
		List<Map<String, Object>> earlyInfoList = attendanceDailyInfoPojo.getEarlyInfoList();
		for(Map<String, Object> earlyInfoMap : earlyInfoList) {
			double earlyDuration = Double.valueOf(earlyInfoMap.get("duration").toString())/1000/60;
			if(earlyDuration>0) {
				for(Map<String, Double> punishMap : punishList) {
					if(punishMap==null || punishMap.get("clocking")==null || punishMap.get("clocking")<=0) {
						break;
					}
					if(earlyDuration<=punishMap.get("clocking")) {
						earlyDeduction += punishMap.get("clockingCharge");
						break;
					}
				}
				if(earlyDeduction==0) earlyDeduction += earlyDuration*(hourlySalary/60);
			}
		}
		List<Map<String, Object>> leaveInfoList = attendanceDailyInfoPojo.getLeaveInfoList();
		double leaveHours = 0;//请假小时数
		for(Map<String, Object> leaveInfoMap : leaveInfoList) {
			if(leaveInfoMap.get("duration") != null) leaveHours += Double.valueOf(leaveInfoMap.get("duration").toString())/1000/60/60;
		}
		List<Map<String, Object>> overtimeInfoList = attendanceDailyInfoPojo.getOvertimeInfoList();
		double overtimeHours = 0;
		for(Map<String, Object> overtimeInfoMap : overtimeInfoList) {
			//加班小时数
			overtimeHours += overtimeInfoMap.get("duration")==null?0:Double.valueOf(overtimeInfoMap.get("duration")==null?"0":overtimeInfoMap.get("duration").toString())/1000/60/60;
		}
		//以半小时为单位计算，不足的不计算例如：加班1.82小时=1.5小时
		overtimeHours = overtimeHours-overtimeHours%0.5;
		return new ImmutableMap.Builder<String, Double>()
				.put("effectiveTimeHours",effectiveTimeHours)
				.put("absentTimeHours",absentTimeHours)
				.put("lateDeduction",lateDeduction)
				.put("earlyDeduction",earlyDeduction)
				.put("leaveHours",leaveHours)
				.put("overtimeHours",overtimeHours)
				.build();
	}
	
	/**
	 * 判断时间节点是否在请假范围内
	 * @param leaveList 请假审批信息
	 * @param baseCheckTime 时间节点
	 * @return true：在请假范围内
	 * @author 王荣
	 */
	public static boolean isLeave(List<Map<String, Object>> leaveList,long baseCheckTime) {
//		long baseCheckTime = ondutyCheck == null ? ondutyTime : offdutyTime;
		for(Map<String, Object> leaveMap : leaveList) {
			if(Long.valueOf(leaveMap.get("startTime").toString())<=baseCheckTime
					&& baseCheckTime<=Long.valueOf(leaveMap.get("endTime").toString())) {
				return true;
			}
		}
		return false;
	}
	
	public static double getRealSalary(double attendanceSalary,double socialSecurity,double accumulationFund,double otherDeduction,double otherAddition) {
		//实际薪水=出勤工资-社保-公积金-其他减项+其他加项
		return attendanceSalary-socialSecurity-accumulationFund-otherDeduction+otherAddition;
	}
	
	/**
	 * 计算实发工资
	 * @param attendanceSalary 出勤工资
	 * @param pieceWage 计件工资
	 * @param otherAddition 其他加项
	 * @param deductions 扣款项：社保、公积金、其他扣款、水电、补料扣款
	 * @return
	 * @author 王荣
	 */
	public static double getRealSalary(double salary,double otherAddition,double...deductions) {
		//计件工资>出勤工资 则用计件工资计算
//		double realSalary = pieceWage > attendanceSalary ? pieceWage : attendanceSalary;
		double realSalary = salary;
		realSalary += otherAddition;
		for(double deduction : deductions) {
			realSalary -= deduction;
		}
		return realSalary;
	}
	
	/**
	 * 筛选打卡记录，除最后一次下班外，上班取最早，下班取最晚
	 * @param clockInfoList
	 * @author 王荣
	 * @throws ParseException 
	 */
	public static List<WorkdateClockInfo> getClockList(List<WorkdateClockInfo> clockInfoList,int clockTimes,String attendanceTime) throws ParseException {
		//如果是奇数次打卡 并且打卡次数大于正常打卡次数 则最后一条打卡无效
		/*if(clockInfoList.size()>clockTimes&&clockInfoList.size()%2!=0) {
			clockInfoList.remove(clockInfoList.size()-1);
		}*/
		String[] attendanceTimeArray = attendanceTime.replace(" ", "-").split("-");
		List<WorkdateClockInfo> clockDatas = new ArrayList<>();
		//根据checkType分组，再根据checkType判断上下班从分组中筛选
		if(clockInfoList.size()<=0) return clockDatas;
		Map<Integer, List<WorkdateClockInfo>> map = clockInfoList.stream()
				.filter(info -> info.getCheckType()!=null)
				.collect(Collectors.groupingBy(WorkdateClockInfo::getCheckType));
		for(Integer checkType : map.keySet()) {
			List<WorkdateClockInfo> datas = map.get(checkType);
			//如果一个时间点不止一次打卡 && 不是最后一次下班(2,4代表下班)
			if(datas.size()>1 && (checkType!=2||checkType!=4) ) {
				//上下班都取最早
				//clockDatas.add(datas.get(0));
				
				//上下班都取最早
				//如果打卡时间时间在排班时间最后一个排班时间之后则全部放进去 否则取第一条数据
				
				String userCheckTime = JSONObject.fromObject(datas.get(0)).get("userCheckTime").toString();
				Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(userCheckTime); 
				userCheckTime = new SimpleDateFormat("HH:mm").format(date);
				System.out.println(userCheckTime+"====="+attendanceTimeArray[attendanceTimeArray.length-1]);
				if(userCheckTime.compareTo(attendanceTimeArray[attendanceTimeArray.length-1])>=0) {
					//放入全部
					for(WorkdateClockInfo data : datas) {
						clockDatas.add(data);
					}
				}else if(AttendanceUtil.stampToDate(AttendanceUtil.dateToStamp(datas.get(0).getBaseCheckTime(), "yyyy-MM-dd HH:mm:ss"), "HH:mm").equals(attendanceTimeArray[attendanceTimeArray.length-1])){
					//放入全部
					for(WorkdateClockInfo data : datas) {
						clockDatas.add(data);
					}
				}else {
					clockDatas.add(datas.get(0));
				}
			}else {
				//放入全部
				for(WorkdateClockInfo data : datas) {
					clockDatas.add(data);
				}
			}
		}
		//重新计算setCheckType
		//排序
		List<WorkdateClockInfo> list = clockDatas.stream().sorted(Comparator.comparing(WorkdateClockInfo::getBaseCheckTime)).collect(Collectors.toList());
		int index = 1;
		for(WorkdateClockInfo workdateClockInfo : list) {
			System.out.println(workdateClockInfo);
			if(index!=attendanceTimeArray.length) {
				workdateClockInfo.setCheckType(index);
				index++;
			}else {
				workdateClockInfo.setCheckType(attendanceTimeArray.length);
			}
		}
		return list;
	}
	
	/**
	 * 筛选打卡记录，除最后一次下班外，上班取最早，下班取最晚
	 * @param clockInfoList
	 * @param clockTimes
	 * attendanceTime 代表排班
	 * @author 王荣
	 */
	public static List<Map<String, Object>> getClockList2(List<Map<String, Object>> clockInfoList,int clockTimes ,String attendanceTime) {
		//根据checkType分组，再根据checkType判断上下班从分组中筛选
		List<Map<String, Object>> list = clockInfoList.stream()
				.filter(e -> e.get("checkType")!=null)
				.collect(Collectors.groupingBy(e -> Integer.parseInt(e.get("checkType").toString())))
				.entrySet().stream().map(e -> {
					Map<String, Object> map = new HashMap<>();
					map.put("checkType", e.getKey());
					map.put("clockList", e.getValue());
					return map;
				}).collect(Collectors.toList());
		List<Map<String, Object>> clockDatas = new ArrayList<>();
		for(Map<String, Object> m : list) {
			int checkType = Integer.valueOf(m.get("checkType").toString());
			@SuppressWarnings("unchecked")
			List<Map<String, Object>> datas = (List<Map<String, Object>>) m.get("clockList");
			int size = datas.size();
			//如果一个时间点不止一次打卡 && 不是最后一次下班(2,4代表下班)
			if(size>1 && (checkType!=2||checkType!=4) && list.size()!=1) {
				//上下班都取最早
				//如果打卡时间时间在排班时间最后一个排班时间之后则全部放进去 否则取第一条数据
				String[] attendanceTimeArray = attendanceTime.replace(" ", "-").split("-");
				String userCheckTime = JSONObject.fromObject(datas.get(0)).get("userCheckTime").toString();
				userCheckTime = AttendanceUtil.stampToDate(userCheckTime, "HH:mm");
				System.out.println(userCheckTime+"====="+attendanceTimeArray[attendanceTimeArray.length-1]);
				if(userCheckTime.compareTo(attendanceTimeArray[attendanceTimeArray.length-1])>=0) {
					//放入全部
					for(Map<String, Object> data : datas) {
						clockDatas.add(data);
					}
				}else if(AttendanceUtil.stampToDate(datas.get(0).get("baseCheckTime").toString(), "HH:mm").equals(attendanceTimeArray[attendanceTimeArray.length-1])){
					//放入全部
					for(Map<String, Object> data : datas) {
						clockDatas.add(data);
					}
				}else {
					clockDatas.add(datas.get(0));
				}
			}else {
				//放入全部(包括休息加班)
				for(Map<String, Object> data : datas) {
					clockDatas.add(data);
				}
			}
		}
		return clockDatas;
	}
	
	/**
	 *時間轉換 毫秒數转换成时分
	 * @param time
	 * @return
	 */
	public static String getGapTime(double time){
		int hours = (int)(time / (1000 * 60 * 60));
		double minutes = (time-hours*(1000 * 60 * 60 ))/(1000* 60);
		String diffTime="";
		if(minutes<10){
			diffTime=hours+"小时0"+minutes+"分钟";
		}else{
			diffTime=hours+"小时"+minutes+"分钟";
		}
		return diffTime;
	}
	
	/* 
     	* 将时间戳转换为时间
     */
    public static String stampToDate(String s,String format){
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }
    /* 
 	* 将时间戳转换为时间
 */
public static String dateToStamp(String s,String format) throws ParseException{
	SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
	Date date = simpleDateFormat.parse(s);
	String res = date.getTime()+"";
    return res;
}
    
    /**
     * objectTomap
     * @param obj
     * @return
     */
    private static Map<String, Object> obj2Map(Object obj) {
        Map<String, Object> map=new HashMap<String, Object>();
        Field[] fields=obj.getClass().getDeclaredFields(); // 获取对象对应类中的所有属性域
        for (int i = 0; i < fields.length; i++) {
            String varName = fields[i].getName();
            varName=varName.toUpperCase();///将key置为大写，默认为对象的属性
            boolean accessFlag=fields[i].isAccessible(); // 获取原来的访问控制权限
            fields[i].setAccessible(true);// 修改访问控制权限
            try {
                Object object =fields[i].get(obj); // 获取在对象中属性fields[i]对应的对象中的变量
                if (object!=null) {
                    map.put(varName, object);
                }else {
                    map.put(varName, null);
                }
                fields[i].setAccessible(accessFlag);// 恢复访问控制权限
            } catch (IllegalArgumentException | IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return map;
    }
    
    public static String formatTime(Long ms) {
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;
 
        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;
        
        StringBuffer sb = new StringBuffer();
        if(day > 0) {
            sb.append(day+"天");
        }
        if(hour > 0) {
            sb.append(hour+"小时");
        }
        if(minute > 0) {
            sb.append(minute+"分");
        }
        if(second > 0) {
            sb.append(second+"秒");
        }
        if(milliSecond > 0) {
            sb.append(milliSecond+"毫秒");
        }
        return sb.toString();
    }
    
	public static void main(String[] args) {
        /*double ms = 537300000;
        Double mss = 537300000d;
        System.out.println(AttendanceUtil.getGapTime(mss));
        SimpleDateFormat formatter = new SimpleDateFormat("HH小时mm分钟");//这里想要只保留分秒可以写成"mm:ss"
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        String hms = formatter.format(ms);
        System.out.println(hms);*/
		/*System.out.println(AttendanceUtil.stampToDate("1559468220000", "HH:mm"));
		JSONObject jsonObject = JSONObject.parseObject("{a:1,b:2}");
		System.out.println(jsonObject.get("a"));*/
		Map<String, String> map = new HashMap<String, String>();
        map.put( "1", "aaa" );
        map.put( "2", "bbb" );
        map.put( "3", "ccc" );
        map.put( "4", "ddd" );
        map.put( "5", "eee" );
        map.put( "6", "fff" );
        map.put( "7", "ggg" );
        map.put( "8", "hhh" );
        System.out.println(map);
        JSONObject jsonObject = JSONObject.fromObject(map);
        System.out.println(jsonObject.get("1"));
    }
	
}
